home *** CD-ROM | disk | FTP | other *** search
/ The Mac 13 / the-mac-13.iso / Shareware City / Utilities / setext2html / setext2html.pl < prev   
Encoding:
Perl Script  |  1995-06-05  |  16.8 KB  |  774 lines  |  [TEXT/R*ch]

  1. #!/usr/bin/perl
  2.   eval "exec /usr/bin/perl -S $0 $*"
  3.   if $running_under_some_shell;
  4. # Copyright Hans Verbrugge 1995
  5. # hans@solair1.inter.nl.net
  6. #
  7. # $Id: setext2html.pl,v 1.4 1995/06/04 13:20:39 hans Exp hans $
  8. #
  9. # this script translates setext formatted files
  10. # to html formatted files
  11. #
  12. #
  13. #
  14. # YOU, THE USER OF THIS SOFTWARE WILL USE THIS SOFTWARE AT YOUR OWN RISK.
  15. # IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  16. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  17. # DAMAGES.
  18. #
  19. # based on setext.pl,v 2.8
  20. # by Tony Sanders <sanders@earth.com>
  21.  
  22. #_______ NOT SUPPORTED (YET) _______
  23. # digests
  24. # multisetext
  25. # href_tt
  26. # hot_tt, will only be diplayed as strong emphasized.
  27.  
  28. #_______ TODO ________
  29. # be more economical on memory usage
  30.  
  31.  
  32. #_______ HISTORY ________
  33.  
  34. ######
  35. # v1.0, Hans Verbrugge
  36. # - initial version, never made it public
  37. #
  38.  
  39. ######
  40. # v1.1b1, Hans Verbrugge
  41. # - implemented chapter (on title_tt) splitting
  42.  
  43.  
  44.  
  45. ######
  46. # v1.1b2, Hans Verbrugge
  47. # - when splitting chapters , overview file gets the title of the 
  48. #   first chapter + "Overview"
  49. # - when splitting chapters, prefixes for output files 
  50. #   and the name of the index file
  51. #   are userdefined
  52.  
  53. ######
  54. # v1.1b3, Hans Verbrugge
  55. # - made preparations to make this run under Unix
  56.  
  57. ######
  58. # v1.1b4, Hans Verbrugge
  59. # - url's are translated properly
  60.  
  61. ######
  62. # v1.1b5, Hans Verbrugge
  63. # - url's are not properly translated when it contains a ':portnumber'.
  64. #   fixed
  65. # - handle url's first, translate setext special chars
  66. #   like '_' into escape sequences so that further parsing
  67. #   leaves the url alone
  68.  
  69. ######
  70. # v1.1, Robert A. Lentz <lentz@annie.astro.nwu.edu>
  71. #       Hans Verbrugge
  72. # - fixed argument parsing
  73. # - fixed chdir bug 
  74.  
  75. ######
  76. # v1.2, Hans Verbrugge
  77. # - my perl version for linux (v5.000) goes bananas 
  78. #   when feeded large regular expression substitutions.
  79. #   Those are now splitted into seperate subroutines.
  80. #   (DoUrl/SubstUrl/DoMail/SubstMail)
  81.  
  82. ######
  83. # v1.3, Hans Verbrugge
  84. # - when no files are specified on commandline
  85. #   read from stdin
  86.  
  87. ######
  88. # v1.4, Hans Verbrugge
  89. # - implemented quote-tt handling
  90.  
  91. #_______ GLOBALS _______
  92. # comment if you're not running this on a mac
  93. $MACINTOSH=1;
  94.  
  95. #_______ OPTIONS _______
  96.  
  97. if (defined ($MACINTOSH)) {
  98.   require "StandardFile.pl";
  99.   
  100.   # CONFIGURABLE PARAMETERS FOR MAC USERS
  101.    
  102.   # set to '0' if you don't want your chapters
  103.   # stored into separate files
  104.   $SPLIT_ON_CHAPTERS=0;
  105.  
  106.   # set to '0' if you don't want
  107.   # mail addresses to be translated to the MAILTO: url
  108.   $DO_MAIL = 1;
  109.    
  110.   # set to '0' if you don't want
  111.   # url's to be translated.
  112.   $DO_URL = 1;
  113.  
  114.   # set to '0' if you don't care what's going on :-)
  115.   $VERBOSE = 1;
  116.   
  117.   # when splitting on chapters, this becomes the overview file,
  118.   # rename it if you want another name
  119.   $INDEX_FILE_PREFIX="index";
  120.   
  121.   # when splitting on chapters, this becomes the prefix name of
  122.   # the output file, so in this case chapter 1 gets stored in ch-1.html
  123.   # rename it if you want another name
  124.   $CHAPTER_PREFIX="ch-";
  125.   
  126. }
  127. else {
  128.   # default settings for unix
  129.   $SPLIT_ON_CHAPTERS=0;
  130.   $DO_MAIL = 0;
  131.   $DO_URL = 0;
  132.   $VERBOSE = 0;
  133.   $INDEX_FILE_PREFIX="index";
  134.   $CHAPTER_PREFIX="ch-";
  135.   
  136.   #get current directory
  137.   $DIR = `pwd`;
  138.   chop ($DIR);
  139.  
  140.   
  141. }
  142. $SECTION=0;
  143. $CHAPTER_NO=0;
  144.  
  145. $title="";
  146. $firstchapter="";
  147. $stylechange="";
  148.  
  149. #_______ arrays _______
  150. %FILES=();
  151. %SPLITTED_CHAPTERS=();
  152. $lines="";
  153. $hrefs="";
  154.  
  155.  
  156. #_______ states _______
  157.  
  158. $INDENT = 1;
  159. $MONO =2;
  160. $PREFORMAT = 3;
  161. $STATE = $INDENT;
  162. $UNFOLDING = 0;
  163.  
  164.  
  165. # html styles
  166. $html_addr=                         "ADDRES";
  167. $html=                              "HTML";
  168. $html_head=                         "HEAD";
  169. $html_body=                         "BODY";
  170. $html_title=                        "TITLE";
  171. $html_bold=                         "B";
  172. $html_italic=                       "I";
  173. $html_uline=                        "EM";
  174. $html_emph=                         "EM";
  175. $html_strongemph=                   "STRONG";
  176. $html_block=                        "BLOCKQUOTE";
  177. $html_preformat=                    "PRE";
  178. $html_paragraphbreak=               "P";
  179.  
  180. #_______ setext styles _______
  181. $title_tt=                          "^(={2,})\\s*\$";
  182. $subhead_tt=                        "^(-{2,})\\s*\$";
  183. $indent_tt=                         "^  ";
  184. $bold_tt=                           "\\*\\*([^\\*]*)\\*\\*";
  185. $italic_tt=                         "~([^\\s]*)~";
  186. $underline_tt=                      "_([^\\s]*)_";
  187. $hot_tt=                            "\\b([^\\s]*)_\\b";
  188. $include_tt=                        "^>\\s*(.*)";
  189. $bullet_tt=                         "^\\*\\s+(.*)";
  190. $quote_tt=                          "`_(\\b+)_`";
  191.  
  192.  
  193.  
  194. #### MAIN ####
  195. while ($ARGV[0] =~ /^[^-].*/) {
  196.   $_ = shift @ARGV;
  197.   $FILES{$_}="";
  198.  
  199. }
  200.  
  201. if (! defined ($MACINTOSH)) {
  202.   &parseopts();
  203. }
  204.  
  205. # on a mac ask for input if no files were found in @ARGV
  206. if (! %FILES && defined ($MACINTOSH)) {
  207.    $ifile = &StandardFile'GetFile("open source file:", "TEXT", "TEXT");
  208.    $ifile eq '' && &Fail ("no input file given!\n");
  209.    $FILES{$ifile} = "bla";
  210. }
  211.  
  212. # on a mac set stderr unbuffered if we are in verbose mode
  213. if ($VERBOSE == 1 && defined ($MACINTOSH)) {
  214.   select (stderr); $| = 1; select (stderr);
  215. }
  216.  
  217. # on a mac let user choose a folder to save splitted files,
  218. # on unixbox directory was given on the commandline
  219. if ($SPLIT_ON_CHAPTERS == 1) {
  220.   if (defined $MACINTOSH) {
  221.     $DIR = &MacChooseOuput();
  222.   }
  223.   # split the chapters in directory $DIR
  224.   &SplitChapters($DIR);
  225.   
  226.   # now change directory to $DIR 
  227.   chdir ($DIR) || &Fail ("cd $DIR: $!\n");
  228. }
  229. else {
  230.   # force a loop when reading from stdin
  231.   if (! %FILES) {$FILES{"USE SINPUT"} = "";}
  232. }
  233.  
  234. print STDERR "parsing ...\n" if $VERBOSE;
  235.  
  236. foreach $file (sort keys %FILES) {
  237.   local ($ofile) = $FILES{$file};
  238.   
  239.   if (defined $MACINTOSH && ! $SPLIT_ON_CHAPTERS) {
  240.     $ofile = &MacChooseOuput($file);
  241.   }
  242.   &do_it ($file, $ofile);
  243. }
  244. if ($SPLIT_ON_CHAPTERS) {
  245.   foreach $file (sort keys %FILES) {
  246.     unlink $file;
  247.   }
  248.   &BuildContents(); 
  249. }
  250.  
  251. print STDERR "done\n" if $VERBOSE;
  252. exit 0;
  253.  
  254. ############## 
  255.  
  256. sub parseopts
  257. {
  258.   while (@ARGV) {
  259.     $_ = shift (@ARGV);
  260.  
  261.     if    (/^-v$/) {$VERBOSE = 1;}
  262.     elsif (/^-m$/) {$DO_MAIL = 1;}
  263.     elsif (/^-u$/) {$DO_URL = 1;}
  264.     elsif (/^-s$/) {$SPLIT_ON_CHAPTERS = 1;}
  265.     elsif (/^-d(.*)/) {$DIR = $1 ? $1 : shift(@ARGV);}
  266.     elsif (/^-i(.*)/) {$INDEX_FILE_PREFIX = $1 ? $1 : shift(@ARGV);}
  267.     elsif (/^-p(.*)/) {$CHAPTER_PREFIX = $1 ? $1 : shift(@ARGV);}
  268.     elsif (/^-(.)/) {
  269.       print STDERR "unrecognized option: $_\n";
  270.       &Usage;
  271.       exit (1);
  272.     }
  273.     else {
  274.       print STDERR "unrecognized token: $_\n";
  275.       &Usage();
  276.       exit (1);
  277.     }
  278.   }
  279. }
  280.  
  281.  
  282. # build the contents file when splitting on chapters
  283. sub BuildContents 
  284. {
  285.   print STDERR "building ${INDEX_FILE_PREFIX}.html...\n" if $VERBOSE;
  286.   
  287.   open (CONTENTS,">${INDEX_FILE_PREFIX}.html") || 
  288.     &Fail ("${INDEX_FILE_PREFIX}.html:$!\n");
  289.   print CONTENTS <<"EOF";
  290. <${html}>
  291. <${html_head}>
  292. <${html_title}>${firstchapter} Overview</${html_title}>
  293. </${html_head}>
  294. <${html_body}>
  295. <H2><CENTER>${firstchapter} Overview</CENTER></H2><P>
  296. <HR>
  297. <UL>
  298. EOF
  299.  
  300.   # translate funny chars back to html   
  301.   grep (do {&XlateSpecialChars} && 0,%SPLITTED_CHAPTERS);
  302.  
  303.   foreach $key (sort bynumber keys %SPLITTED_CHAPTERS) {
  304.     $file = ${CHAPTER_PREFIX} . ${key};
  305.     print CONTENTS "  <LI><A HREF=\"${file}.html\">$SPLITTED_CHAPTERS{$key}</A>\n";
  306.   }
  307.   print CONTENTS <<"EOF";
  308. </UL>
  309. <P>
  310. <HR>
  311. </${html_body}>
  312. </${html}>
  313. EOF
  314. }
  315.  
  316.  
  317.  
  318. # do_it; parse input ifile and write to output file ofile
  319. sub do_it
  320. {
  321.   local ($ifile,$ofile) = @_;
  322.   local ($i);
  323.   local ($key);
  324.   
  325.   if ($ifile eq "USE SINPUT") {
  326.     open (IFILE, "<&STDIN") || &Fail ("couldn't dup stdin:$!\n");
  327.   }
  328.   else {
  329.     open (IFILE,$ifile) || &Fail ("$file:$!\n");
  330.   }
  331.  
  332.   # fill lines array; 
  333.     
  334.   $lines = "";
  335.   $#lines=0;
  336.  
  337.   while (<IFILE>) {
  338.     chop;
  339.     # eat white
  340.     $_=~s/\s+$//go;     
  341.     $lines[$.-1]=$_;
  342.   }
  343.   close (IFILE);
  344.   
  345.   if ($ofile eq '') {
  346.     open (OUTFILE, ">&STDOUT") || &Fail ("couldn't dup stdout:$!\n");
  347.   }
  348.   else {
  349.     open (OUTFILE,">${ofile}") || &Fail ("Couldn't create ${ofile}:$!\n");
  350.   }
  351.  
  352.   # translate special characters in
  353.   # their html counterparts
  354.   grep (do {&TranslateSpecialChars} && 0,@lines);  
  355.  
  356.   # process subheads & titles
  357.   &HandleSubheads;
  358.  
  359.   print "      $title...\n" if $VERBOSE;
  360.  
  361.   # translate funny chars back to html    
  362.   grep (do {&TranslateSpecialCharsBack} && 0,@hrefs);
  363.   # build the header
  364.   &MakeHeader;
  365.  
  366.   print OUTFILE "<${html_body}>\n";
  367.   print OUTFILE "<H2><CENTER>$title</CENTER></H2><P>\n";
  368.   print OUTFILE "<HR>";
  369.   print OUTFILE "<UL>\n";
  370.   for ($i = 0; $i <= $#hrefs; $i++) {
  371.     print OUTFILE "  <LI>$hrefs[$i]\n";
  372.   }
  373.   print OUTFILE "</UL>\n";
  374.   print OUTFILE "<P>";
  375.   #print OUTFILE "<HR>";
  376.  
  377.   &ParseSetext;
  378.  
  379.   # translate special characters in
  380.   # their html counterparts
  381.   #&TranslateSpecialCharsBack;
  382.   grep (do {&TranslateSpecialCharsBack} && 0,@lines);
  383.  
  384.   for ($i = 0; $i <= $#lines; $i++) {
  385.   $_ = $lines[$i];
  386.     print OUTFILE "$_\n" unless /^\.\. /; 
  387.   }
  388.   print OUTFILE "</${html_body}>\n";
  389.   close (OUTFILE);
  390. }
  391.  
  392. sub CheckForSetext
  393. {
  394.   local ($file) = @_;
  395.   
  396.   open (IFILE,$file) || &Fail ("Couldn't open $file:\n$!");
  397.   
  398.   while (<IFILE>) {
  399.     if (/^==*/ || /^--*/) {
  400.       close (IFILE);
  401.       return 1;
  402.     }
  403.   }
  404.   return 0;
  405. }
  406.   
  407. sub Fail
  408. {
  409.   local ($why)=@_;
  410.  
  411.   if (defined ($MACINTOSH))
  412.   {
  413.     &MacPerl'Answer ("$why", "Bye");
  414.     exit;
  415.   }
  416.   else 
  417.   {
  418.     die "$why";
  419.   }
  420. }
  421.  
  422. # open the input file, if script runs on a Mac
  423. # ask the user where to save the new file
  424. # otherwise print open STDOUT
  425.  
  426. sub MacChooseOuput
  427. {
  428.   local ($ifile) = @_;
  429.   
  430.   if (defined ($MACINTOSH))
  431.   {
  432.        local ($file,$ofile);
  433.     
  434.     if ($SPLIT_ON_CHAPTERS != 1) {
  435.       $file = $1 if $ifile =~ /([^:]*)$/;  # basename
  436.  
  437.       $ofile = &StandardFile'PutFile("Save htmlized version as:", "$file.html");
  438.       exit unless $ofile;
  439.       return $ofile;
  440.     }
  441.     else {
  442.       local ($folder) = &StandardFile'GetFolder("save chapters where?");
  443.       exit unless $folder;
  444.       return $folder;
  445.     }
  446.   }
  447. }
  448.  
  449. # translate special characters to a nonprintable char
  450. # so we can recognize it later.
  451. # primary use is to *not* screw up HREFS in chapter overviews
  452.  
  453. sub XlateSpecialChars
  454. {
  455.   s/&/&/go;
  456.   s/</</go;
  457.   s/>/>/go unless /^>/;
  458.   s/"/"/go;
  459.   s/ö/ö/go;
  460.   s/ñ/ñ/go;
  461.   s/È/È/go;
  462.   
  463. }
  464.  
  465. sub TranslateSpecialChars
  466. {
  467.   s/&/\01/go;
  468.   s/</\02/go;
  469.   s/>/\03/go unless /^>/;
  470.   s/"/\04/go;
  471.   s/ö/\05/go;
  472.   s/ñ/\06/go;
  473.   s/È/\07/go;
  474.   
  475. }
  476.  
  477. sub TranslateSpecialCharsBack
  478. {
  479.   s/\01/&/go;
  480.   s/\02/</go;
  481.   s/\03/>/go;
  482.   s/\04/"/go;
  483.   s/\05/ö/go;
  484.   s/\06/ñ/go;
  485.   s/\07/È/go;
  486. }
  487.  
  488.  
  489. sub SplitChapters
  490. {
  491.   local ($dir) = @_;
  492.   local ($file) = "";
  493.   local ($i,$_);
  494.   local ($firstLineIsChapter);
  495.   local ($currentdir) = `pwd`;
  496.   
  497.   chop ($currentdir);
  498.     
  499.   print STDERR "splitting...\n" if $VERBOSE;
  500.  
  501.   # force a loop when no input files where given
  502.   if (! %FILES) {$FILES{"USE SINPUT"} = "";}
  503.   
  504.   foreach $file (sort keys %FILES) {
  505.     if ($file eq "USE SINPUT") {
  506.       open (IFILE, "&STDIN") || &Fail ("couldn't dup stdin:$!\n");
  507.     }
  508.     else {
  509.       open (IFILE,$file) || &Fail ("$file:$!\n");
  510.     }
  511.     chdir $dir || &Fail ("cd $dir:$!\n");
  512.  
  513.     # fill lines array; 
  514.        while (<IFILE>) {
  515.          chop;
  516.          # eat white
  517.          $_=~s/\s+$//go;     
  518.          $lines[$.-1]=$_;
  519.        }
  520.        close (IFILE);
  521.        $firstLineIsChapter = 0;
  522.  
  523.        for ($i = 0; $i <= $#lines; $i++) {
  524.          $_ = $lines[$i];
  525.     
  526.          # check for title_tt
  527.       if (/$title_tt/) {
  528.            if (length ($_) == length ($lines[$i-1])) {
  529.              # got a title_tt 
  530.            
  531.              $i == 1 && ($firstLineIsChapter = 1);
  532.              (($i > 1) && ($firstLineIsChapter == 0)) &&
  533.                &Fail("$file: when splitting on chapters,\nfirst line in the file should be title_tt\n");
  534.            
  535.              $firstchapter = $lines[$i-1] unless $firstchapter;
  536.              $lines[$i-1] = "\033\036" . $lines[$i-1];
  537.     
  538.              print STDERR "      ", substr ($lines[$i-1],2), "\n" if $VERBOSE;
  539.            } 
  540.          }
  541.        }
  542.        for ($i = 0; $i <= $#lines; $i++) {
  543.        $_ = $lines[$i];
  544.     
  545.        if (s#^\033\036(.*)#$1#go) {
  546.          close (CHAPTER) if ($CHAPTER_NO++ > 1);
  547.          local ($splittedfile) = "${CHAPTER_PREFIX}${CHAPTER_NO}";
  548.            open (CHAPTER,">${splittedfile}") || &Fail ("${splittedfile}:$!\n");
  549.          $SPLITTED_CHAPTERS{"$CHAPTER_NO"}=$_;
  550.        }
  551.        print CHAPTER $_,"\n";
  552.     }
  553.     close (CHAPTER);
  554.  
  555.        # back to working direcory
  556.        chdir($currentdir);
  557.   }
  558.   # rebuild %FILES array
  559.   %FILES=();
  560.     
  561.   foreach $key (sort bynumber keys %SPLITTED_CHAPTERS) {
  562.     $file = ${CHAPTER_PREFIX} . ${key};
  563.     $FILES{$file} = "${file}.html"
  564.   }
  565. }
  566.  
  567.  
  568.  
  569. # handle subheads & titles;
  570. # the lines are stripped from trailing whitespace,
  571. # if a line is followed by a line containing a equal
  572. # number of '=' or '-' starting at position 1,
  573. # then that line is a valid title_tt or subhead_tt.
  574. sub HandleSubheads
  575. {
  576.   local ($issetext)=0;
  577.   local ($y)=0;
  578.   local ($i,$_);
  579.  
  580.   $title="";
  581.   $#hrefs=0;
  582.   $SECTION = 0;
  583.   
  584.   for ($i = 0; $i <= $#lines; $i++) {
  585.     $_ = $lines[$i];
  586.  
  587.     # check for title_tt
  588.     if (/$title_tt/) {
  589.       if (length ($_) == length ($lines[$i-1])) {
  590.         $SECTION++;
  591.         $issetext = 1;
  592.         $title = $lines[$i-1] unless $title ne "";
  593.         $hrefs[$y++]="<A HREF=\"\#sub${SECTION}\">$lines[$i-1]</A>";
  594.         $lines[$i-1]=~s#(.*)#  <HR>\n  <H2><A NAME=\"sub${SECTION}\">$1</A></H2>#;     
  595.         $lines[$i] = '.. ';
  596.         next;        
  597.       }
  598.     }
  599.      
  600.     # check for subhead_tt
  601.     elsif (/$subhead_tt/) {
  602.       if (length ($_) == length ($lines[$i-1])) {
  603.         $SECTION++;
  604.         $issetext = 1;
  605.         $hrefs[$y++]="<A HREF=\"\#sub${SECTION}\">$lines[$i-1]</A>";
  606.         $lines[$i-1]=~s#(.*)#  <HR>\n  <H3><A NAME=\"sub${SECTION}\">$1</A></H3>#;
  607.         $lines[$i] = '.. ';
  608.         next;
  609.       }
  610.     }
  611.   }
  612.  
  613.   # if we don't have a setext file, die!
  614.   &Fail ("not a setext file!\n") unless $issetext == 1;
  615.  
  616. }
  617.  
  618. sub MakeHeader
  619. {
  620.   print OUTFILE "<${html_head}>\n";
  621.   &PrintHtmlStyle ($html_title, $title) unless ($title eq "");
  622.   print OUTFILE "</${html_head}>\n";
  623. }
  624.  
  625. sub ParseSetext
  626. {
  627.   local ($i, $_);
  628.  
  629.   for ($i = 0; $i <= $#lines; $i++) {
  630.     $_ = $lines[$i];
  631.     
  632.     next if (/^\.\. /);
  633.  
  634.     if ($STATE == $INDENT && /^$/) {
  635.       $lines[$i] .= "\n<${html_paragraphbreak}>\n" unless $UNFOLDING++;
  636.       #print OUTFILE "<${html_paragraphbreak}>\n" unless $UNFOLDING++;
  637.       next;
  638.     }
  639.     $UNFOLDING = 0;
  640.    
  641.     # state transitions
  642.     if (/^>\s/) { &to_mono; }
  643.     elsif (/^  [^ ]/) { &to_fmt; }
  644.     else { &to_pre; }
  645.  
  646.     s/^>\s*//;                                      # fix quote-tt
  647.     s/^  ([^ ])/\1/;                                # fix indent-tt
  648.  
  649.      # quote-tt
  650.       &DoQuote();
  651.   
  652.     # urls
  653.     $DO_URL == 1 && &DoUrl();
  654.    
  655.     # mail adresses
  656.     $DO_MAIL == 1 && &DoMail();
  657.  
  658.  
  659.     
  660.     # bullet_tt
  661.       s#^\*\s+(.*)#<UL><LI>$1</UL>#o;
  662.  
  663.     # bold_tt
  664.       s#\*\*([^\*]*)\*\*#<$html_bold>$1</$html_bold>#go;
  665.  
  666.     # italic_tt
  667.       s#~([^\s]*)~#<$html_italic>$1</$html_italic>#go; 
  668.  
  669.     # underline_tt                                                
  670.       s#_([^\s]*)_#($a = $1) =~ s,_, ,g; "\<$html_uline\>$a\<\/$html_uline\>"; #ge;
  671.  
  672.     # hot_tt
  673.         s#\b([^\s]*)_\b#<$html_strongemph>$1</$html_strongemph>#go;  
  674.  
  675.     s,\0331,_,go;
  676.     s,\0332,~,go;
  677.     s,\0333,",go;
  678.     s,\0334,*,go;
  679.     $lines[$i] = join ('',$stylechange,$_);
  680.   }
  681. }
  682.  
  683. sub DoUrl 
  684. {
  685.   s#(ftp|http|wais|telnet|gopher|news)(://[\w-\+]+)(([\.~][\w-\+/\*:\?_\#]+){0,})#&SubstUrl();#ge;
  686. }
  687.  
  688. sub SubstUrl
  689. {
  690.   local ($a) = join ('',$1,$2,$3);
  691.   $a =~ s,_,\0331,go; 
  692.   $a =~ s,~,\0332,go;
  693.   return "<A HREF=\0333$a\0333>$a</A>";
  694. }
  695.  
  696. sub DoMail
  697. {
  698.   s#([\w-\+.!]+[@!][\w-\+]+)((\.[\w-\+]+){0,})#&SubstMail();#ge;
  699. }
  700.  
  701. sub SubstMail
  702. {
  703.   local ($a) = join ('',$1,$2);
  704.   $a =~ s,_,\0331,go;
  705.   $a =~ s,~,\0332,go;
  706.   return "<A HREF=\0333mailto:$a\0333>$a</A>";
  707. }
  708.  
  709.  
  710. sub DoQuote
  711. {
  712.   # quoted typotags should be passed unmodified,
  713.   # change typetags special chars to escape sequences
  714.  
  715.   s#'_(.*)!_'#&SubstQuote();#ge;
  716. }
  717.  
  718.  
  719. sub SubstQuote
  720. {
  721.   local ($a) = $1;
  722.   $a =~ s,_,\0331,go;
  723.   $a =~ s,~,\0332,go;
  724.   $a =~ s,\*,\0334,go;
  725.  
  726.   return "$a"; 
  727. }
  728.  
  729. sub PrintHtmlStyle
  730. {
  731.   local ($style, $what) = @_;
  732.   
  733.   print OUTFILE "\<$style\>$what\<\/$style\>\n";
  734. }
  735.  
  736. sub to_fmt {
  737.   $STATE == $INDENT && do {$stylechange = ""; return};
  738.   
  739.   $stylechange = "</PRE>\n" if $STATE == $PREFORMAT;
  740.   $stylechange = "</PRE></BLOCKQUOTE>\n" if $STATE == $MONO;
  741.  
  742.   $STATE = $INDENT;
  743. }
  744. sub to_pre {
  745.   $STATE == $PREFORMAT && do {$stylechange = ""; return};
  746.  
  747.   $stylechange = "<PRE>\n" if $STATE == $INDENT;
  748.   $stylechange = "</PRE></BLOCKQUOTE><PRE>\n" if $STATE == $MONO;
  749.  
  750.   $STATE = $PREFORMAT;
  751. }
  752. sub to_mono {
  753.   $STATE == $MONO && do {$stylechange = ""; return};
  754.  
  755.   $stylechange = "<BLOCKQUOTE><PRE>\n" if $STATE == $INDENT;
  756.   $stylechange = "</PRE><BLOCKQUOTE><PRE>\n" if $STATE == $PREFORMAT;
  757.  
  758.   $STATE = $MONO;
  759. }
  760.  
  761. sub bynumber {$a <=> $b}
  762.  
  763. sub Usage
  764. {
  765.   $0 = $1 if $0 =~ /([^\/]*)$/;  # basename
  766.  
  767.   print STDERR <<"EOF";
  768. $0 usage: $0 [file(s)] [-v] [-m] [-u]
  769.              [-s [-d directory -i indexprefix -p filesprefix]]
  770. EOF
  771. }
  772.